home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
wtek0693.zip
/
OOPALLEY.ZIP
/
DATE.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-27
|
17KB
|
551 lines
#include "date.h"
#include "strclass.h"
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "oopsconf.h" //-gmv Added for conditional compilation
// of code for todays date
// See Date::Date()
#include "object.h"
//#define BORLAND // -gmv 3/29/90 as above
#define THIS Date
#define BASE Object
DEFINE_CLASS(Date,Object);
static const unsigned char days_in_month[12] =
{
31,28,31,30,31,30,31,31,30,31,30,31
};
static const dayTy first_day_of_month[12] =
{
1,32,60,91,121,152,182,213,244,274,305,335
};
static const char* month_names[12] =
{
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"
};
static const char* uc_month_names[12] =
{
"JANUARY", "FEBRUARY", "MARCH",
"APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER",
"OCTOBER", "NOVEMBER", "DECEMBER"
};
static const char* week_day_names[7] =
{
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
"Sunday"
};
static const char* uc_week_day_names[7] =
{
"MONDAY", "TUESDAY", "WEDNESDAY",
"THURSDAY", "FRIDAY", "SATURDAY",
"SUNDAY"
};
//static const unsigned int seconds_in_day = 24*60*60;
static const unsigned long seconds_in_day = 24L*60*60; //-gmv made long
void Date::setDate(int dayCount, yearTy referenceYear)
//////////////////////////////////////////////////////
///// Set the day and year of a Date object to /////
///// the dayCount day of the referenceYear. /////
///// The dayCount may be <= 0, in which case /////
///// the Date is that of a year prior to the /////
///// referenceYear. /////
//////////////////////////////////////////////////////
{
register int day = dayCount;
register unsigned year = referenceYear;
register unsigned yearDays;
while (day > (yearDays = daysInYear(year))) {
year++;
day -= yearDays;
}
while (day<=0) day += daysInYear(--year);
dy = day; yr = year;
}
Date::Date()
//////////////////////////////////////////////
////// Construct a Date for today. //////
//////////////////////////////////////////////
{
time_t clk = time(&clk);
register tm* now = localtime(&clk);
setDate(now->tm_yday+1, now->tm_year+1900);
}
Date::Date(int dayCount, yearTy referenceYear)
//////////////////////////////////////////////
////////// Construct a Date //////////
////////// that is dayCount days //////////
////////// after the beginning of //////////
////////// the reference year. //////////
//////////////////////////////////////////////
{
setDate(dayCount,referenceYear);
}
//Date::Date(int dayCount)
Date::Date(long dayCount) //-gmv
///////////////////////////////////
///// Construct a Date /////
///// that is dayCount days /////
///// after January 1, 1901. /////
///////////////////////////////////
{
setDate(1 + (dayCount>=0 ? dayCount%1461 : -((-dayCount)%1461)),
1901 + 4*((dayCount>=0) ? dayCount/1461 : -((-dayCount)/1461)));
}
////////////////////////////////////////////////////////////
// 4/24/93 -gmv
// The following function was added to resolve ambiguity
// in the statement cerr << this
// between 'operator <<(ostream &,void *)'
// and 'operator <<(ostream &,const void *)'
// when 'this' is printed in Date::Date.
// The ambiguity is resolved by providing an
// operator<< function which accepts a pointer
// to an Object (rather than a void pointer)
// as its second argument.
////////////////////////////////////////////////////////////
inline ostream _FAR & _Cdecl operator<<(ostream &o, Object /* far */ *p)
{
return operator<<(o, (void*) p);
}
Date::Date(dayTy day, const char* monthName, yearTy year)
/////////////////////////////////////
///// Construct a Date object /////
///// for the specified day, /////
///// monthName, and year. /////
/////////////////////////////////////
{
if (year < 100) year += 1900;
unsigned monthNumber = numberOfMonth(monthName);
unsigned daysInMonth = days_in_month[monthNumber-1];
if (monthNumber == 2 && leapYear(year)) daysInMonth++;
unsigned firstDayOfMonth = first_day_of_month[monthNumber-1];
if (monthNumber > 2 && leapYear(year)) firstDayOfMonth++;
//if (day<1 || day>daysInMonth)
// setOOPSerror(OOPS_BADMODAY,DEFAULT,this,day,monthName,year);
//if (day<1 || day>daysInMonth)
// DTerror("Invalid day of month: ", className());
if (day<1 || day>daysInMonth)
{
DTerror("","");
cerr << "Invalid day of month: "
///////////////////////////////////////////////
// 4/24/93 -gmv had to add inline function
// above to resolve ambiguity for cerr << this
// between 'operator <<(ostream &,void *)'
// and 'operator <<(ostream &,const void *)'
///////////////////////////////////////////////
<< this << "->Date::Date("
<< day << ","
<< monthName << ","
<< year << ")"
<< "\n";
}
setDate(day-1+firstDayOfMonth,year);
}
static void skipDelim(istream& strm)
{
char c;
if (!strm.good()) return;
strm >> c;
while (strm.good() && !isalnum(c)) strm >> c;
strm.putback(c);
}
static const char* parseMonth(istream& strm)
////////////////////////////////////////////
///// Read the name of a month from /////
///// the specified input stream. /////
////////////////////////////////////////////
{
static char month[10];
register char* p = month;
char c;
skipDelim(strm);
strm.get(c);
while (strm.good() && isalpha(c) && (p != &month[10])) {
*p++ = c;
strm.get(c);
}
if (strm.good()) strm.putback(c);
*p = '\0';
return month;
}
static Date parseDate(istream& strm)
////////////////////////////////////////////////////////////////////
///// Read a date from the specified /////
///// input stream in any of the /////
///// following forms: /////
///// /////
///// <day><monthName><year> (5 April 1982; 5-APR-82) /////
///// <monthName><day><year> (April 5, 1982) /////
///// <monthNumber><day><year> (4/5/82) /////
////////////////////////////////////////////////////////////////////
{
unsigned d,m,y;
const char* mon; // name of month
if (strm.good()) {
skipDelim(strm);
strm >> m; // try to parse day or month number
skipDelim(strm);
if (strm.eof()) return Date(1,1901);
if (strm.fail()) { // parse <monthName><day><year>
strm.clear();
mon = parseMonth(strm); // parse month name
skipDelim(strm);
strm >> d; // parse day
}
else { // try to parse day number
strm >> d;
if (strm.eof()) return Date(1,1901);
if (strm.fail()) { // parse <day><monthName><year>
d = m;
strm.clear();
mon = parseMonth(strm); // parse month name
}
else { // parsed <monthNumber><day><year>
mon = nameOfMonth(m);
}
}
skipDelim(strm);
strm >> y;
}
if (!strm.good()) return Date(1,1901);
return Date(d,mon,y);
}
Date::Date(istream& strm) { *this = parseDate(strm); }
dayTy dayOfWeek(const char* dayName)
//////////////////////////////////////
///// Returns the number, 1-7, /////
///// of the day of the week /////
///// named dayName. /////
//////////////////////////////////////
{
{
String s(dayName);
register unsigned len = s.size();
if (len > 2) {
s.toUpper();
register const char* p = s;
for (register unsigned i =0; i<7; i++)
if (strncmp(p,uc_week_day_names[i],len)==0) return i+1;
}
}
//setOOPSerror(OOPS_BADDAYNAM,DEFAULT,dayName);
//DTerror("Date: Invalid day of week: ", dayName);
DTerror("","");
cerr << "Invalid day of week name: "
<< dayName
<< "\n";
return 0; // never executed
}
dayTy daysInYear(yearTy year)
////////////////////////////////////////
///// Returns the number of days /////
///// in the specified year. /////
////////////////////////////////////////
{
return leapYear(year) ? 366 : 365;
}
monthTy numberOfMonth(const char* monthName)
///////////////////////////////////////////
///// Returns the number, 1-12, /////
///// of the month named monthName. /////
///////////////////////////////////////////
{
{
String s(monthName);
register unsigned len = s.size();
if (len > 2) {
s.toUpper();
register const char* p = s;
for (register unsigned i =0; i<12; i++)
if (strncmp(p,uc_month_names[i],len)==0) return i+1;
}
}
//setOOPSerror(OOPS_BADMONAM,DEFAULT,monthName);
//DTerror("Invalid month name", monthName);
DTerror("","");
cerr << "Invalid month name: "
<< monthName
<< "\n";
return 0; // never executed
}
bool leapYear(yearTy year)
//////////////////////////////////////////
///// Returns YES if the specified /////
///// year is a leap year. /////
//////////////////////////////////////////
{
return ((year&3) == 0 && year%100 != 0 || year%400 == 0);
}
const char* nameOfMonth(monthTy monthNumber)
/////////////////////////////////////////
///// Returns the name of the /////
///// month numbered monthNumber. /////
/////////////////////////////////////////
{
//if (--monthNumber >= 12)
// setOOPSerror(OOPS_BADMONTH,DEFAULT,monthNumber+1);
//if (--monthNumber >= 12)
// DTerror("Invalid month", "");
if (--monthNumber >= 12)
{
DTerror("","");
cerr << "Invalid month: "
<< monthNumber+1
<< "\n";
}
return month_names[monthNumber];
}
const char* nameOfDay(dayTy weekDayNumber)
////////////////////////////////////////////////
///// Returns the name of the day /////
///// specified by weekDayNumber: /////
///// Monday == 1, ... , Sunday == 7 /////
////////////////////////////////////////////////
{
//if (--weekDayNumber >= 7)
// setOOPSerror(OOPS_BADDAY,DEFAULT,weekDayNumber+1);
//if (--weekDayNumber >= 7)
// DTerror("Invalid day of week: ", "");
if (--weekDayNumber >= 7)
{
DTerror("","");
cerr << "Invalid day of week: "
<< weekDayNumber+1
<< "\n";
}
return week_day_names[weekDayNumber];
}
bool Date::operator<(Date dt) const
//////////////////////////////
// Return YES if this Date //
// is < the argument Date. //
//////////////////////////////
{
if (yr < dt.yr) return YES;
if (yr == dt.yr && dy < dt.dy) return YES;
return NO;
}
bool Date::operator<=(Date dt) const
//////////////////////////////
// Return YES if this Date //
// is <= the argument Date. //
//////////////////////////////
{
if (yr < dt.yr) return YES;
if (yr == dt.yr && dy <= dt.dy) return YES;
return NO;
}
//int Date::operator-(Date dt)
long Date::operator-(Date dt) const
////////////////////////////////////////
///// Return the number of days /////
///// between this Date and /////
///// the argument. The result /////
///// is negative if the argument /////
///// is later. /////
////////////////////////////////////////
{
Date a(*this),b(dt);
// const Date a(*this), b(dt); // -gmv 5/2/90 made const
bool negative = b > a;
if (negative)
{
a = b;
b = *this;
}
unsigned year = b.year();
long days = signed(a.day()-b.day()); //-gmv
while (year != a.year()) days += daysInYear(year++);
return negative ? -days : days;
}
const char* Date::nameOfMonth() const
{
return ::nameOfMonth(month());
}
monthTy Date::month() const
///////////////////////////////////////
///// Returns the number, 1-12, /////
///// of this Date's month. /////
///////////////////////////////////////
{
//register bool leapYear = leap(); // -gmv 5/2/90 Why is this here?
register unsigned firstDay;
for (register unsigned mn =12; mn>0; mn--) {
firstDay = first_day_of_month[mn-1];
if (mn > 2 && leap()) firstDay++;
if (firstDay <= dy) return mn;
}
//setOOPSerror(OOPS_BADMONTH,DEFAULT,mn);
//DTerror("Invalid month: ", className());
DTerror("","");
cerr << "Invalid month: "
<< mn
<< "\n";
return 0; // never executed
}
dayTy Date::firstDayOfMonth(monthTy month) const
///////////////////////////////////////////////
///// Returns the number of the day /////
///// of the year that is the first day /////
///// of the month in this Date's year. /////
///////////////////////////////////////////////
{
register unsigned firstDay = first_day_of_month[month-1];
if (month > 2 && leap()) firstDay++;
return firstDay;
}
Date Date::previous(const char* dayName) const
////////////////////////////////////////////
///// Returns the previous date /////
///// whose weekday name is dayName. /////
////////////////////////////////////////////
{
return *this - (7 + weekDay() - dayOfWeek(dayName))%7;
}
dayTy Date::weekDay() const
/////////////////////////////////////
///// Return the number, 1-7, /////
///// of the day of the week /////
///// for this Date. /////
/////////////////////////////////////
{
register unsigned yearNumber;
register unsigned dayNumber;
if (dy < firstDayOfMonth(3)) {
yearNumber = yr-1;
dayNumber = 307;
}
else {
yearNumber = yr;
dayNumber = -58-leap();
}
return (dayNumber + dy + yearNumber
+ (yearNumber/4) + (yearNumber/400)
- (yearNumber/100)) % 7 + 1;
}
bool Date::between(Date min, Date max) const
/////////////////////////////////////////
///// Return YES if this Date /////
///// is <= to max and >= to min. /////
/////////////////////////////////////////
{
return *this >= min && *this <= max;
}
dayTy Date::dayOfMonth() const
{
return dy-firstDayOfMonth()+1;
}
Date Date::max(Date dt) const
{
if (dt < *this)
return *this;
return dt;
}
Date Date::min(Date dt) const
{
if (dt > *this)
return *this;
return dt;
}
int Date::compare(const Object& ob) const
{
int t;
assertArgSpecies(ob,class_Date,"compare");
if ((t=yr-((Date*)&ob)->yr) != 0) return t;
else return (dy-((Date*)&ob)->dy);
}
Object* Date::copy() const { return shallowCopy(); }
void Date::deepenShallowCopy() {}
unsigned Date::hash() const { return dy^yr; }
bool Date::isEqual(const Object& ob) const
{
return ob.isSpecies(class_Date) && *this==*(Date*)&ob;
}
const Class* Date::species() const { return &class_Date; }
void Date::printOn(ostream& strm) const
{
#if 0
strm << form("%2d-%.3s-%.2d",
dayOfMonth(),
nameOfMonth(),
yr%100);
#else
char saveFillChar = strm.fill();
long saveFlags = strm.flags();
strm.width(2);
strm.fill(' ');
strm << dayOfMonth() << "-";
char monthAbbreviation[4];
strncpy(monthAbbreviation, nameOfMonth(), 3);
monthAbbreviation[3] = '\0';
strm << monthAbbreviation << "-";
//strm << nameOfMonth() << "-";
strm.width(2);
strm.fill('0');
strm << yr%100;
strm.fill(saveFillChar);
strm.flags(saveFlags);
#endif
}
void Date::scanFrom(istream& strm)
{
*this = parseDate(strm);
}
#if 0
Date::Date(istream& strm, Date& where)
{
this = &where;
strm >> dy >> yr;
}
// -gmv stripped 5/3/90
#endif